use crate::db::Db;
use crate::redis::*;
use crate::util::*;
use anyhow::{Result, anyhow};
use rumqttc::v5::AsyncClient;
use tokio_cron_scheduler::{JobBuilder, JobScheduler};
use tokio_graceful_shutdown::SubsystemHandle;
use tracing::{error, info};

pub async fn run(subsys: SubsystemHandle, db: Db, redis: Redis, client: AsyncClient) -> Result<()> {
    let mut sched = JobScheduler::new().await?;
    let redis_1 = redis.clone();
    let client_1 = client.clone();
    sched
        .add(
            JobBuilder::new()
                .with_timezone(chrono_tz::Asia::Shanghai)
                .with_cron_job_type()
                .with_schedule("0/10 * * * * *")?
                .with_run_async(Box::new(move |_, _| {
                    let redis_1_1 = redis_1.clone();
                    let client_1_1 = client_1.clone();
                    Box::pin(async move {
                        let _ = publish_pings(&client_1_1, redis_1_1)
                            .await
                            .inspect_err(|e| error!("cron task 'publish_pings' error -- {}", e));
                    })
                }))
                .build()?,
        )
        .await?;
    let db_2 = db.clone();
    let redis_2 = redis.clone();
    sched
        .add(
            JobBuilder::new()
                .with_timezone(chrono_tz::Asia::Shanghai)
                .with_cron_job_type()
                .with_schedule("0 0/1 * * * *")?
                .with_run_async(Box::new(move |_, _| {
                    let db_2_1 = db_2.clone();
                    let redis_2_1 = redis_2.clone();
                    Box::pin(async move {
                        let _ = drop_space_unused(db_2_1, redis_2_1).await.inspect_err(|e| {
                            error!("cront task 'clear_inactive_spaces' error -- {}", e)
                        });
                    })
                }))
                .build()?,
        )
        .await?;
    sched.set_shutdown_handler(Box::new(|| {
        Box::pin(async { info!("cron scheduler has been shutdown") })
    }));
    sched.start().await?;
    subsys.on_shutdown_requested().await;
    sched.shutdown().await.map_err(|e| anyhow!(e))
}
